package com.flow.framework.schedule.executor;

import com.flow.framework.common.constant.FrameworkCommonConstant;
import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.json.JsonObject;
import com.flow.framework.common.util.verify.VerifyUtil;
import com.flow.framework.core.holder.SystemVersionContextHolder;
import com.flow.framework.core.response.Response;
import com.flow.framework.core.system.helper.AsyncHelper;
import com.flow.framework.schedule.system.listener.lifecycle.JobResourceHolder;
import com.flow.framework.schedule.job.BaseScheduleJob;
import com.flow.framework.schedule.properties.local.LocalConfigProperties;
import com.flow.framework.schedule.properties.local.sub.SubLocalConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.slf4j.MDC;

import java.util.List;

/**
 * 本地调度执行者
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/4/9
 */
@Slf4j
@DisallowConcurrentExecution
public class LocalScheduleJobExecutor implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            MDC.clear();
            SystemVersionContextHolder.clear();
            MDC.put(FrameworkCommonConstant.GLOBAL_LOG_TRACE_KEY, AsyncHelper.randomAsyncTraceId());
            JobKey jobKey = context.getJobDetail().getKey();
            String jobName = jobKey.getName();
            LocalConfigProperties localConfigProperties = JobResourceHolder.getLocalConfigProperties(jobName);
            if (null == localConfigProperties) {
                log.warn("can't find local config, job maybe canceled, bean name : {}", jobName.split(":")[0]);
                return;
            }
            String beanName = localConfigProperties.getBeanName();
            BaseScheduleJob bean = JobResourceHolder.getBean(beanName);
            if (null == bean) {
                log.error("can't find job bean, bean name : {}", beanName);
                throw new CheckedException(SystemErrorCode.OBJECT_NOT_FOUND_ERROR);
            }
            bean.cacheSelf(bean);
            String params = localConfigProperties.getParams();
            bean.setJobName(jobName);
            Response<String> response = bean.schedule(params);
            log.debug("schedule current job success, response : {}", JsonObject.toString(response));
            List<SubLocalConfigProperties> subs = localConfigProperties.getSubs();
            if (VerifyUtil.isEmpty(subs)) {
                return;
            }
            subs.forEach(subLocalConfigProperties -> {
                String subJobBeanName = subLocalConfigProperties.getBeanName();
                BaseScheduleJob subJobBean = JobResourceHolder.getBean(subJobBeanName);
                if (null == subJobBean) {
                    log.error("can't find sub job bean, sub job bean name : {}", subJobBeanName);
                    throw new CheckedException(SystemErrorCode.OBJECT_NOT_FOUND_ERROR);
                }
                String subJobParams = subLocalConfigProperties.getParams();
                subJobBean.setJobName(jobName);
                Response<String> subJobResponse = subJobBean.schedule(subJobParams);
                log.debug("schedule sub job success, response : {}", JsonObject.toString(subJobResponse));
            });
            log.debug("schedule job success");
        } catch (Exception e) {
            log.error("local schedule error.", e);
        } finally {
            MDC.clear();
            SystemVersionContextHolder.clear();
        }
    }
}
